package com.iterator.service.web.goodsManager;

import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;

import com.iterator.bean.web.pojo.Category;
import com.iterator.bean.web.pojo.tcy.*;
import com.iterator.bean.web.tcy.*;
import com.iterator.mapper.web.goodsManager.*;

import com.iterator.exceptions.ArgsException;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;

/**
 * @author tean_cy
 * @date 2021/1/9 22:56
 */
@Service
public class GoodsServiceImpl implements GoodsService {

    @Autowired
    GoodsMapper goodsMapper;

    @Autowired
    CategoryMapper categoryMapper;

    @Autowired
    BrandsMapper brandsMapper;

    @Autowired
    GoodsAttributeMapper goodsAttributeMapper;

    @Autowired
    GoodsSpecificationMapper goodsSpecificationMapper;

    @Autowired
    GoodsProductMapper goodsProductMapper;


    /**
     * 商品列表admin/goods/list
     *
     * @return
     */
    @Override
    public GoodsListVO list(Integer page, Integer limit, String goodSn, String name, String sort, String order) {
        // 创建一个criteria对象，通过改对象可以调用逆向工程已经实现好的方法
        GoodsExample goodsExample = new GoodsExample();
        GoodsExample.Criteria criteria = goodsExample.createCriteria();

        // 在没有条件搜素时，goodSn和name可能为空，因此需要进行判断，只有不为空时才能在查询条件上拼接
        if (!StringUtils.isEmpty(goodSn)) {
            //andGoodsSnEqualTo 等价于查询语句中where后面条件为goodsn=#{goodSn}
            criteria.andGoodsSnEqualTo(goodSn);
        }
        if (!StringUtils.isEmpty(name)) {
            //andNameLike等价于查询语句中where后面条件为name like %xxx%
            criteria.andNameLike("%" + name + "%");
        }
        //查询到的记录一定要是没有被删除的，因此需要拼接deleted为false状态
        criteria.andDeletedEqualTo(false);
        //升序或者是降序排列
        goodsExample.setOrderByClause(sort + " " + order);
        //分页，一定要导入PageHelper依赖
        PageHelper.startPage(page, limit);

        //因为查询有一个特殊的text字段，表示的文本类型，因此不能使用selectByExample方法
        List<Goods> goods = goodsMapper.selectByExampleWithBLOBs(goodsExample);
        //对查询结果统计
        PageInfo<Goods> goodsPageInfo = new PageInfo<>(goods);
        long total = goodsPageInfo.getTotal();

        return new GoodsListVO(total, goods);
    }


    /**
     * 商品品牌admin/goods/catAndBrand(为上架页面提供品牌信息)
     *
     * @return
     */
    @Override
    public CatAndBrandVO catAndBrand() {

        //selectAll方法：
        //先根据pid 查询出所有的父类，pid = 0
        //然后根据父类的id = 子类的pid查询父类下的子类，将其封装
        List<CategoryData> categoryDataList = categoryMapper.selectAll();
        List<BrandData> brandDataList = brandsMapper.selectAll();

        CatAndBrandVO catAndBrandVO = new CatAndBrandVO(categoryDataList, brandDataList);
        return catAndBrandVO;
    }

    /**
     * 商品更新admin/goods/update
     *
     * @param updateBO
     * @return
     */
    @Override
    @Transactional
    public int update(GoodsAddAndUpdateBO updateBO) {
        Date date = new Date();
        Goods goods = updateBO.getGoods();
        goods.setUpdateTime(date);
        int i = goodsMapper.updateByPrimaryKeySelective(goods);

        List<GoodsAttribute> attributes = updateBO.getAttributes();

        // 该逻辑为表中含有数据只需要增加的
        for (GoodsAttribute attribute : attributes) {
            attribute.setUpdateTime(date);
            attribute.setGoodsId(goods.getId());

            GoodsAttributeExample goodsAttributeExample = new GoodsAttributeExample();
            GoodsAttributeExample.Criteria criteria = goodsAttributeExample.createCriteria();
            criteria.andGoodsIdEqualTo(attribute.getGoodsId());

            int update = goodsAttributeMapper.updateByExampleSelective(attribute, goodsAttributeExample);
            if (update == 0) {
                throw new ArgsException("更新失败");
            }
        }

        List<GoodsSpecification> specifications = updateBO.getSpecifications();
        // 该逻辑为更新逻辑
        for (GoodsSpecification specification : specifications) {
            specification.setUpdateTime(date);
            specification.setGoodsId(goods.getId());

            GoodsSpecificationExample goodsSpecificationExample = new GoodsSpecificationExample();
            GoodsSpecificationExample.Criteria criteria = goodsSpecificationExample.createCriteria();
            criteria.andGoodsIdEqualTo(goods.getId());
            int update = goodsSpecificationMapper.updateByExampleSelective(specification, goodsSpecificationExample);
            if (update == 0) {
                throw new ArgsException("更新失败");
            }
        }

        List<GoodsProduct> products = updateBO.getProducts();
        for (GoodsProduct product : products) {
            product.setUpdateTime(date);
            product.setGoodsId(goods.getId());

            GoodsProductExample goodsProductExample = new GoodsProductExample();
            GoodsProductExample.Criteria criteria = goodsProductExample.createCriteria();
            criteria.andGoodsIdEqualTo(goods.getId());
            int update = goodsProductMapper.updateByPrimaryKeySelective(product);
            if (update == 0) {
                throw new ArgsException("更新失败");
            }
        }
        return i;
    }

    /**
     * 商品详情admin/goods/detail
     *
     * @param id
     * @return
     */
    @Override
    public GoodsDetailVO detail(Integer id) {
        //查goods表
        Goods goods = goodsMapper.selectByPrimaryKey(id);
        //查attribute表,根据的是goodsId，要确保delete的状态是false
        GoodsAttributeExample goodsAttributeExample = new GoodsAttributeExample();
        GoodsAttributeExample.Criteria criteria = goodsAttributeExample.createCriteria();
        criteria.andGoodsIdEqualTo(id).andDeletedEqualTo(false);
        List<GoodsAttribute> goodsAttributes = goodsAttributeMapper.selectByExample(goodsAttributeExample);

        //查product表
        GoodsProductExample goodsProductExample = new GoodsProductExample();
        GoodsAttributeExample.Criteria criteria1 = goodsAttributeExample.createCriteria();
        criteria1.andGoodsIdEqualTo(id).andDeletedEqualTo(false);
        List<GoodsProduct> goodsProducts = goodsProductMapper.selectByGoodsId(id);

        //查specifications表
        GoodsSpecificationExample example = new GoodsSpecificationExample();
        GoodsSpecificationExample.Criteria criteria2 = example.createCriteria();
        criteria2.andGoodsIdEqualTo(id).andDeletedEqualTo(false);
        List<GoodsSpecification> goodsSpecifications = goodsSpecificationMapper.selectByExample(example);

        //查category表
        Integer categoryId = goods.getCategoryId();
        Category category = categoryMapper.selectByPrimaryKey(categoryId);
        Integer pid = category.getPid();
        List<Integer> categoryIds = new ArrayList<>();
        categoryIds.add(pid);
        categoryIds.add(categoryId);

        //封装所有查询记录
        GoodsDetailVO goodsDetailVO = new GoodsDetailVO(categoryIds, goods,
                goodsAttributes, goodsSpecifications, goodsProducts);
        return goodsDetailVO;
    }

    /**
     * 商品删除admin/goods/delete
     */
    @Override
    @Transactional
    public int delete(Goods goods) {
        Integer id = goods.getId();

        // 删除goods表
        goods.setDeleted(true);
        int update1 = goodsMapper.updateByPrimaryKeySelective(goods);
        if (update1 == 0) {
            throw new ArgsException("删除失败");
        }

        // 删除product表,根据goodId
        GoodsProductExample goodsProductExample = new GoodsProductExample();
        GoodsProductExample.Criteria criteria = goodsProductExample.createCriteria();
        criteria.andGoodsIdEqualTo(id);

        // 删除之前先查询是否存在，不存在则不需要删除
        List<GoodsProduct> goodsProducts = goodsProductMapper.selectByExample(goodsProductExample);
        if (goodsProducts.size() != 0) {
            GoodsProduct goodsProduct = new GoodsProduct();
            goodsProduct.setDeleted(true);

            int update2 = goodsProductMapper.updateByExampleSelective(goodsProduct, goodsProductExample);
            if (update2 == 0) {
                // 如果删除失败，抛出异常，回滚其他以被删除的表
                throw new ArgsException("删除失败");
            }
        }

        // 删除specification表，逻辑同上表

        GoodsSpecificationExample goodsSpecificationExample = new GoodsSpecificationExample();
        GoodsSpecificationExample.Criteria criteria1 = goodsSpecificationExample.createCriteria();
        criteria1.andGoodsIdEqualTo(id);

        List<GoodsSpecification> goodsSpecifications = goodsSpecificationMapper.selectByExample(goodsSpecificationExample);
        // 查询到该表才需要删除
        if (goodsSpecifications.size() != 0) {
            GoodsSpecification goodsSpecification = new GoodsSpecification();
            goodsSpecification.setDeleted(true);

            int update3 = goodsSpecificationMapper.updateByExampleSelective(goodsSpecification, goodsSpecificationExample);
            if (update3 == 0) {
                throw new ArgsException("删除失败");
            }
        }


        //删除product表
        GoodsAttributeExample goodsAttributeExample = new GoodsAttributeExample();
        GoodsAttributeExample.Criteria criteria2 = goodsAttributeExample.createCriteria();
        criteria2.andGoodsIdEqualTo(id);

        List<GoodsAttribute> goodsAttributes = goodsAttributeMapper.selectByExample(goodsAttributeExample);
        int update4 = -1;
        if (goodsAttributes.size() != 0) {
            GoodsAttribute goodsAttribute = new GoodsAttribute();
            goodsAttribute.setDeleted(true);
            update4 = goodsAttributeMapper.updateByExampleSelective(goodsAttribute, goodsAttributeExample);
            if (update4 == 0) {
                throw new ArgsException("删除失败");
            }
        }
        return update4;
    }

    /**
     * 商品上架admin/goods/create
     */
    @Override
    @Transactional
    public int create(GoodsAddAndUpdateBO createBO) {

        //添加之前需要去商品数据库比对是否存在已有的商品编号
        String goodsSn = createBO.getGoods().getGoodsSn();
        List<String> strings = goodsMapper.selectGoodsSn();
        for (String string : strings) {
            if (goodsSn.equals(string)) {
                return 205;
            }
        }

        //添加goods表
        Date date = new Date();
        Goods goods = createBO.getGoods();
        if (goods == null) {
            throw new ArgsException("数据不完整，无法创建");
        }
        goods.setUpdateTime(date);
        goods.setAddTime(date);
        int parseInt = Integer.parseInt(goods.getGoodsSn());
        goods.setId(parseInt);
        goods.setDeleted(false);
        int i = goodsMapper.insertSelective(goods);

        //添加attributes表
        // TODO：要先去判断该请求体中是否有完整的数据
        List<GoodsAttribute> attributes = createBO.getAttributes();
        if (attributes.size() == 0) {
            throw new ArgsException("数据不完整，无法创建");
        }
        for (GoodsAttribute attribute : attributes) {
            attribute.setUpdateTime(date);
            attribute.setAddTime(date);
            attribute.setDeleted(false);
            attribute.setGoodsId(goods.getId());
            int create = goodsAttributeMapper.insertSelective(attribute);
            if (create == 0) {
                return create;
            }
        }

        //添加specification表
        List<GoodsSpecification> specifications = createBO.getSpecifications();
        if (specifications.size() == 0) {
            throw new ArgsException("数据不完整，无法创建");
        }
        for (GoodsSpecification specification : specifications) {
            specification.setUpdateTime(date);
            specification.setAddTime(date);
            specification.setDeleted(false);
            specification.setGoodsId(goods.getId());
            int create = goodsSpecificationMapper.insertSelective(specification);
            if (create == 0) {
                return create;
            }
        }

        //添加product表
        List<GoodsProduct> goodsProducts = createBO.getProducts();
        if (goodsProducts.size() == 0) {
            throw new ArgsException("数据不完整，无法创建");
        }
        for (GoodsProduct goodsProduct : goodsProducts) {
            goodsProduct.setUpdateTime(date);
            goodsProduct.setAddTime(date);
            goodsProduct.setDeleted(false);
            goodsProduct.setGoodsId(goods.getId());
            int create = goodsProductMapper.insertSelective(goodsProduct);
            if (create == 0) {
                return create;
            }
        }
        return i;
    }
}